package com.earogya.springsecurity.security;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.authentication.dao.SaltSource;
import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;

import com.earogya.springsecurity.security.SaltedUser;

/**
 * Extends the baseline Spring Security JdbcDaoImpl and implements change password functionality.
 * 
 * Used in Chapter 4 example of customizing JdbcDaoImpl.
 * 
 * @author Mularien
 */
public class CustomJdbcDaoImpl extends JdbcDaoImpl implements ChangePasswordInterface, CreateUsersInterface, AddUsersToUserGroupsInterface{
	// Ch 4 Password Encoder and Salt Exercise
	@Autowired
	private PasswordEncoder passwordEncoder;
	@Autowired
	private SaltSource saltSource;

	public void changePassword(String username, String password) {
		/*getJdbcTemplate().update(
				"UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?",
				password, username);*/
		// Ch 4 After password encoder and salt exercise
		UserDetails user = loadUserByUsername(username);
		String encodedPassword = passwordEncoder.encodePassword(password, saltSource.getSalt(user));
		getJdbcTemplate().update(
			"UPDATE USERS SET PASSWORD = ? WHERE USERNAME = ?",
			encodedPassword, username);
	}

	// Ch 4 SaltedUser exercise
	//@Override
	protected UserDetails createUserDetails(String username,
			UserDetails userFromUserQuery,
			List<GrantedAuthority> combinedAuthorities) {
        String returnUsername = userFromUserQuery.getUsername();

        if (!isUsernameBasedPrimaryKey()) {
            returnUsername = username;
        }

        return new SaltedUser(returnUsername,((SaltedUser) userFromUserQuery).getName(), userFromUserQuery.getPassword(),((SaltedUser) userFromUserQuery).getEmail(),((SaltedUser) userFromUserQuery).getDepartment(), userFromUserQuery.isEnabled(),
                true, true, true, combinedAuthorities, ((SaltedUser) userFromUserQuery).getSalt());
	}

	@Override
	protected List<UserDetails> loadUsersByUsername(String username) {
        return getJdbcTemplate().query(getUsersByUsernameQuery(), new String[] {username}, new RowMapper<UserDetails>() {
            public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
                String username = rs.getString(1);
                String name = rs.getString(2);
                String password = rs.getString(3);
                String email = rs.getString(4);
                String department = rs.getString(5);
                boolean enabled = rs.getBoolean(6);
                String salt = rs.getString(7);
                //String salt="nkkj";
                return new SaltedUser(username, name,password,email,department, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES, salt);
            }
        });
	}
	
	public void createUser(String username,String name, String password, String email, String department) throws DuplicateKeyException{
		
		//UserDetails user= new User(username, password, true, true, true, true, AuthorityUtils.NO_AUTHORITIES);
		// Ch 4 After password encoder and salt exercise
		//UserDetails user = loadUserByUsername(username);
		 //Object salt=saltSource.getSalt(user);
		String salt= String.valueOf(Math.random()*1000000000);
		String encodedPassword = passwordEncoder.encodePassword(password, salt);
		/*getJdbcTemplate(). update(
			"INSERT INTO USERS VALUES USERNAME = ? , NAME='Ureka', PASSWORD = ?, enabled=true, salt=?",
			username,encodedPassword,saltSource.getSalt(user));*/
		//System.out.print(saltSource.getSalt(user));
		getJdbcTemplate(). update(
				
				"INSERT INTO USERS VALUES (?,?,?,?,?,true,?)",
				username,name,encodedPassword,email,department,salt);
		}
		
	
	
	public void addUsersToUserGroups(String username,int userGroup){
		try{
		int count=getJdbcTemplate(). queryForInt("SELECT count(*) FROM GROUP_MEMBERS WHERE USERNAME=?",new Object[]{username});
			//getJdbcTemplate().query(getUsersByUsernameQuery(), new String[] {username});
			if(count==0){
		getJdbcTemplate(). update(
				
				"INSERT INTO GROUP_MEMBERS(username,group_id) VALUES (?,?)",
				username,userGroup);
	}
			else{
				getJdbcTemplate(). update(
						
						"UPDATE GROUP_MEMBERS SET group_id=? WHERE USERNAME=?",
						userGroup,username);
			}
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		
	}
}
